package com.me.study.javaCore.reflection;

import com.me.common.util.CglibProxyUtil;
import spring.aop.dao.IndexDaoImpl;
import spring.aop.pojo.T2;

import java.lang.annotation.Annotation;
import java.lang.reflect.*;

/**
 * Reflection：通过反射获取方法并且调用
 */
public class MethodReflect {

	public static void main(String[] args) throws Exception {
		//获取Class对象
		Class<?> clazz = Class.forName("java.lang.Runtime");

		// 获取自己声明的所有方法(包括私有方法, 但不包括父类继承)
		Method[] methods = clazz.getDeclaredMethods();
		// Method[] methods = clazz.getMethods();// 获取公开的方法(包括从父类继承的)

		// 输出
		System.out.println("--------------------获得所有自己声明的方法-------------------------");
		for (Method method : methods) {
			if (!"getRuntime".equals(method.getName())) {
				continue;
			}
			// 自定义输出
			// 1.修饰符
			System.out.print(Modifier.toString(method.getModifiers()) + " ");
			// 返回类型
			System.out.print(method.getReturnType().getName() + " ");
			// 方法名
			System.out.print(method.getName() + "(");
			// 参数列表
			Class<?>[] parameters = method.getParameterTypes();
			for (int i = 0; i < parameters.length; i++) {
				System.out.print((i != parameters.length - 1) ? parameters[i]
						.getName() + "," : parameters[i]);
			}
			System.out.println(")");

			// 调用静态方法
			method.invoke(null);
			// 调用实例方法
			// method.invoke(clazz.newInstance());
		}

		// 直接通过 method 就能拿到所有的参数
		System.out.println("\n--------------------获得方法参数名-------------------------");
		Parameter[] params = clazz.getDeclaredMethod("addShutdownHook", Thread.class).getParameters();
		if (params.length > 0) {
			System.out.println("第一个参数名为：" + params[0].getName());
		}

		System.out.println("\n--------------------获得方法参数类型-------------------------");
		Type[] types = CglibProxyUtil.class.getDeclaredMethods()[0].getGenericParameterTypes();
		for (Type type : types) {
			System.out.println("type: " + type);
			// 只有带泛型的参数才是这种Type，所以得判断一下
			if (type instanceof ParameterizedType) {
				System.out.println("泛型参数----");
				ParameterizedType parameterizedType = (ParameterizedType) type;
				// 获取参数的类型
				System.out.println("getRawType: " + parameterizedType.getRawType());
				// 获取参数的类型
				System.out.println("getOwnerType: " + parameterizedType.getOwnerType());
				// 获取参数的泛型列表
				Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
				for (Type type2 : actualTypeArguments) {
					System.out.println("actualTypeArgument: " + type2);
				}
			}
			System.out.println();
		}

		System.out.println("\n--------------------获得方法参数声明里添加的注解-------------------------");
		// void query(@Victor T2 t2)
		Annotation[][] annotations = IndexDaoImpl.class.getDeclaredMethod("query6", T2.class).getParameterAnnotations();
		System.out.println(annotations[0][0]);

	}

}
